package com.sm.honkon.app.utils;

import android.os.Handler;
import android.os.Looper;
import android.os.Message;
import android.serialport.api.SerialPort;

import androidx.annotation.NonNull;

import com.blankj.utilcode.util.ToastUtils;

import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.nio.ByteBuffer;
import java.nio.CharBuffer;
import java.nio.charset.Charset;


/**
 * Created by Administrator on 2017/6/6.
 */

public class SerialPortUtil {

    public static SerialPort serialPort = null;
    public static InputStream inputStream = null;
    public static OutputStream outputStream = null;

    public static Thread receiveThread = null;

    public static boolean flag = false;


    /**
     * 打开串口
     */
    public static void openSrialPort() {
        try {
            serialPort = new SerialPort(new File("/dev/" + IConstant.PORT), IConstant.BAUDRATE, 0);
            inputStream = serialPort.getInputStream();
            outputStream = serialPort.getOutputStream();
            flag = true;
            ToastUtils.showShort("打开串口成功");

            receiveSerialPort();

        } catch (IOException e) {
            ToastUtils.showShort("打开串口失败");
            e.printStackTrace();
        }
    }

    /**
     * 关闭串口
     */
    public static void closeSerialPort() {
        try {
            if (inputStream != null) {
                inputStream.close();
            }
            if (outputStream != null) {
                outputStream.close();
            }
            if (serialPort != null) {
                serialPort.close();
            }
            if (receiveThread != null) {
                receiveThread = null;
            }
            flag = false;

        } catch (IOException e) {
            e.printStackTrace();
        }

    }

    /**
     * 发送指令
     *
     * @param keySound               按键时，该位为 1，喇叭发出短暂的提示音,0反之
     * @param FHROutput              1,表示 喇 叭为 第 一胎 心 输出， 0, 表示 为 第二 胎 心输出
     * @param TOCOReset              宫 缩 压力复位1：进行复位；0：未进行复位。
     * @param FHRVolume              胎心音量等级0： 0 级,01： 1 级,2： 2 级,3： 3 级,4： 4 级,5： 5 级,6： 6 级,7： 7 级
     * @param AutofetalMoveThreshold 自动胎动阈值调节 0 : 10% ,1 : 20%, 2 : 30%, 3 : 40% ,4 : 50% ,5 : 60%, 6 : 70%  ,7 : 80%
     * @param TOCOZero               宫缩压力归零 0： 000 1： 5 , 2： 15 , 3： 20,4： 25 ,5： 30 ,6： 35
     * @param BuiltinWakeupWork      1表 示 探头 内 置唤 醒 器需 要 工作， 0 表示 探 头内 置 唤醒 器 停止工作。
     * @param ModuleWork             模 块 正常 工 作时 该 位为 1, 模块 待 命时 该 位为 0
     */
    public static void setTjCommond(int keySound, int FHROutput,
                                    int TOCOReset, int FHRVolume, int AutofetalMoveThreshold,
                                    int TOCOZero, int BuiltinWakeupWork, int ModuleWork) {
        byte[] sendCommond = new byte[5];

        sendCommond[0] = (byte) 0xFF;
        sendCommond[1] = 0x00;
        sendCommond[2] |= (byte) ((keySound & 0x01) << 5);
        sendCommond[2] |= (byte) ((FHROutput & 0x01) << 4);
        sendCommond[2] |= (byte) ((TOCOReset & 0x01) << 3);
        sendCommond[2] |= (byte) (FHRVolume & 0x07);
        sendCommond[3] |= (byte) ((AutofetalMoveThreshold & 0x07) << 5);
        sendCommond[3] |= (byte) (TOCOZero & 0x07);
        sendCommond[4] |= (byte) ((BuiltinWakeupWork & 0x07) << 1);
        sendCommond[4] |= (byte) (ModuleWork & 0x01);

        sendSerialPort(sendCommond);
    }

    /**
     * 发送指令给串口
     *
     * @param data
     */
    public static void sendSerialPort(byte[] data) {
        try {
            if (outputStream != null) {
                outputStream.write(data);
                outputStream.flush();
            }
        } catch (IOException e) {
            closeSerialPort();
        }
    }

    /**
     * 解析数据
     */
    public static void receiveSerialPort() {
        if (receiveThread != null)
            return;
        //Log.e("SerialPortUtil", "开始获取数据: ");


        receiveThread = new Thread() {
            @Override
            public void run() {
                while (flag) {
                    try {

                        byte[] readData = new byte[10];
                        if (inputStream == null) {
                            //Log.e("SerialPortUtil", "输入流不存在: ");
                            return;
                        }

                        int size = inputStream.read(readData);
                        if (size > 0 && flag) {
                            //解析数据
                            uiHandler.sendMessage(Message.obtain(uiHandler, 1, readData));
                        }
                    } catch (Exception e) {
                        e.printStackTrace();
                        closeSerialPort();
                    }
                }
            }
        };
        receiveThread.start();
    }

    private static Handler uiHandler = new Handler(Looper.getMainLooper()) {
        @Override
        public void handleMessage(@NonNull Message msg) {
            CommondData.getInstance().readDataByte(getByteArrayToIntArray((byte[]) msg.obj));
        }
    };

    private static int[] getByteArrayToIntArray(byte[] byteArray) {
        int[] intArray;
        intArray = new int[byteArray.length];
        for (int i = 0; i < byteArray.length; i++) {
            if ((byteArray[i] & 0x80) == 0) {
                intArray[i] = (int) byteArray[i];
            } else {
                intArray[i] = (((int) byteArray[i]) & 0x0ff);
            }
        }
        return intArray;
    }

    private static byte[] getBytes(char[] chars) {
        Charset charset = Charset.forName("ISO-8859-1");
        CharBuffer cb = CharBuffer.allocate(chars.length);
        cb.put(chars);
        cb.flip();
        ByteBuffer encode = charset.encode(cb);
        return encode.array();
    }
}
